/**
 * 创建动画图表解析函数
 * @param XAxisStart - 起始点的X轴坐标
 * @param XAxisEnd - 终止点的X轴坐标
 * @param YAxisStart - 起始点的Y轴坐标
 * @param YAxisEnd - 终止点的Y轴坐标
 * @returns 返回动画曲线的解析函数，函数输入自变量，返回对应坐标值
 */
const createAnimationDiagramFn = (XAxisStart: number, XAxisEnd: number, YAxisStart: number, YAxisEnd: number) => {
    return function (value: number) {
        // 取值范围和值域限制
        if (value < XAxisStart) return YAxisStart;
        if (value > XAxisEnd) return YAxisEnd;

        // 这里函数曲线为线性函数（如有必要可以整成贝塞尔曲线一样的曲线函数映射关系）
        const progress = (value - XAxisStart) / (XAxisEnd - XAxisStart);
        return YAxisStart + (YAxisEnd - YAxisStart) * progress;
    };
};

const listEl = document.querySelector(".list") as HTMLElement;
const listItems = listEl.querySelectorAll(".item") as NodeListOf<HTMLLIElement>;
const imgEls = document.querySelectorAll("img") as NodeListOf<HTMLImageElement>;

imgEls.forEach(imgEl => {
    imgEl.src = `https://picsum.photos/200/300?random=${Math.random() * Date.now()}`;
});

type MapValue = Partial<Record<keyof CSSStyleDeclaration, (currentXAxis: number) => string | number>>;
const styleStatusMap = new Map<HTMLElement, MapValue>();

const createElementAnimationStatusObj = (
    itemEl: HTMLElement,
    listEl: HTMLElement,
    xAxisStart: number,
    xAxisEnd: number
): MapValue => {
    // 初始状态
    itemEl.style.opacity = "0";
    itemEl.style.transform = "scale(2)";

    const opacity = (currentXAxis: number) => {
        return createAnimationDiagramFn(xAxisStart, xAxisEnd, 0, 1)(currentXAxis);
    };
    const transform = (currentXAxis: number) => {
        return `scale(${createAnimationDiagramFn(xAxisStart, xAxisEnd, 2, 1)(currentXAxis)})`;
    };
    return {
        opacity,
        transform
    };
};

const setMap = () => {
    listItems.forEach((itemEl, index) => {
        styleStatusMap.set(
            itemEl,
            createElementAnimationStatusObj(itemEl, listEl, 100 + index * 100, 100 + (index + 1) * 100)
        );
    });
};
setMap();
// 从 Map 中取出元素，并根据变化的 x 轴值，设置它的实时状态
const updateStyles = (currentXAxis: number, styleStatusMap: Map<HTMLElement, MapValue>) => {
    for (const [element, statusObj] of styleStatusMap) {
        for (const cssProperty in statusObj) {
            const getCurrentStatus = statusObj[cssProperty] as Function;
            element.style[cssProperty] = `${getCurrentStatus(currentXAxis)}`;
        }
    }
};

// 滚动驱动 x 轴变化
document.addEventListener("scroll", () => {
    updateStyles(document.documentElement.scrollTop, styleStatusMap);
});
